electronic.alchemy :: development tips
electronic.alchemy
where the past meets the future
pike > development tips

development tips

Created by hww3. Last updated by hww3, 11 years ago. Version #3.

Module (ie, Java "static") methods in a CMOD

You can have INIT, EXIT and PIKEFUN blocks outside of a PIKECLASS directive. Because modules are already instantiated as objects, this allows your module to have functions as well as classes.

Calling pike functions from within C/CMOD code

Here's some code for calling (whether they're written in c or pike) functions from your C language module code. Remember that you can create objects this way because create is called implicitly, just ask for the class name you want to instantiate:

// this code works for a function that takes one argument.
// you'll have to modify it to get it to understand multiple args.
// args are at top of stack

// look up the function push_text( "Sql.sql_result"); SAFE_APPLY_MASTER("resolv", 1 );

// method is at top of the stack, we want the arg on top stack_swap();

// arg is at top, function is 1 down from the top apply_svalue( Pike_sp-2, 1 );

// result is at top of the stack, function is still one down // and we want to pop it. stack_swap(); pop_stack();

To run the function "query" in the current object with one arg, already on the stack:

// get the identifier for the member we want to call
int i;
i=find_identifier("query", Pike_fp->current_object->prog);

// now call the method with the context of the current object. apply_low(Pike_fp->current_object, i, 1);

Another option:

/* push arguments on stack */ apply(Pike_fp->current_object, "the method", number_of_args);

The return value will be on the stack, don't forget to pop it after you are done with it.

Working with references

Pike utilizes garbage collection and reference counting to handle memory management of pike data objects (strings, arrays, objects, etc). When writing C/CMOD code, you need to tell pike that you explicitly want to keep data around once it passes out of your function, along with the corresponding process of telling pike that you're done with the object afterward. Pike provides methods for doing this (though some methods will add references automatically).

add_ref(svalue val) is used to add a reference to a variable. free_string(pike_string val) and its corresponding friends is used to subtract references and will free the variable if there are no more references to that variable. The name can be confusing but it's best to think of it from the standpoint of your code not knowing whether other code is using your variable. You're just saying that "it's ok by me if you want to free this value." Pike will actually do that when everone who said they wanted to keep it no longer want the value.

Working with arguments

Pike_sp is your key to working with the Pike stack. The top of the stack (ie the last argument passed to your function) is Pike_sp[-1], and the bottom of the stack (or the first argument) is Pike_sp[-args]. Therefore, to get the n~~th argument, where 1 is the first argument, is Pike_sp[-args + n -1].

Alternately, you can use get_all_args() to check to make sure you have the proper number and type of arguments, and place them into variables. If your needs are not terribly complex (I'm pretty sure that it doesn't handle variable argument types or varargs), this might be a good option.

If your function receives incorrect arguments, instead of using Pike_error, use the following:

for too few arguments, use:

SIMPLE_TOO_FEW_ARGS_ERROR("myfunction",1);

for bad arguments, use:

SIMPLE_BAD_ARG_ERROR("myfunction", 1, "array|mapping|whatever");

Looping through Mappings

The NEW_MAPPING_LOOP macro allows you to loop through all elements in a mapping. Note that the keypair name (~~k) is required and is hard coded.

INT32 e; struct keypair *k; NEW_MAPPING_LOOP(mapping->data) { k->ind k->val // both are svalues }

Debugging

courtesy of grubba

If you have the broken pike running in a gdb, you can try running

 call gdb_backtraces()

as well as

 thread apply all bt

The latter should also work when examining a core dump.

If it isn't possible to call gdb_backtraces(), you'll probably want to examine the stack frames by hand. The top-most frame is available as

 p *Pike_interpreter_pointer->frame_pointer

Not categorized | RSS Feed | BackLinks

comments powered by Disqus